/*
 * XListenerManager.java
 * 
 * Copyright (c) 2006 - 2007 Devon Carew
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
 * file except in compliance with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under
 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
 * ANY KIND, either express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

package org.xfc.util;

import java.util.ArrayList;
import java.util.List;

import org.xfc.util.reflect.XReflectObject;

// TODO: parameterize the exception behavior?


/**
 * A utility class to make adding listener support to a class easier.
 * <p>
 * It should be noted that if an RuntimeException occurs while notify listeners of an event,
 * the listener manager just propogates that exception up to the caller. Any remaining listeners
 * in the notification queue will not be aware of the event. 
 * 
 * @author Devon Carew
 */
public class XListenerManager
{
	private List listeners = new ArrayList();
	
	private Class listenerClass;
	
	
	/**
	 * Create a new listener manager.
	 */
	public XListenerManager()
	{
		this(null);
	}
	
	/**
	 * Create a new listener manager. Make sure that when listeners are added to the manager, they
	 * are of the given class.
	 * 
	 * @param listenerClass
	 */
	public XListenerManager(Class listenerClass)
	{
		this.listenerClass = listenerClass;
	}
	
	/**
	 * Add the given listener.
	 * 
	 * @param listener
	 * @throws IllegalArgumentException if the given listener is not the right class object
	 */
	public void addListener(Object listener)
	{
		if (listenerClass != null && !listenerClass.isInstance(listener))
			throw new IllegalArgumentException("listener is not of the type " + listenerClass.getName());
		
		if (!listeners.contains(listener))
			listeners.add(listener);
	}
	
	/**
	 * Remove the given listener.
	 * 
	 * @param listener
	 */
	public void removeListener(Object listener)
	{
		listeners.remove(listener);
	}
	
	/**
	 * @return the list of listeners
	 */
	public List getListeners()
	{
		return listeners;
	}
	
	public void notifyListeners(String methodName)
	{
		for (int i = listeners.size() - 1; i >= 0; i--)
		{
			XReflectObject listener = XReflectObject.createReflectObject(listeners.get(i)); 
			
			listener.invoke(methodName);
		}
	}
	
	public void notifyListeners(String methodName, Object param)
	{
		for (int i = listeners.size() - 1; i >= 0; i--)
		{
			XReflectObject listener = XReflectObject.createReflectObject(listeners.get(i)); 
			
			listener.invoke(methodName, param);
		}
	}
	
	public void notifyListeners(String methodName, Object param1, Object param2)
	{
		for (int i = listeners.size() - 1; i >= 0; i--)
		{
			XReflectObject listener = XReflectObject.createReflectObject(listeners.get(i)); 
			
			listener.invokeVarArgs(methodName, new Object[] { param1, param2 } );
		}
	}
	
}
